<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用材质覆盖属性</title>
    <script src="js/three69.js"></script>
    <script src="js/Stats.js"></script>
    <script src="js/dat.gui.js"></script>
    <style>
        body{
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<div id="WebGL-output"></div>
<div id="Stats-output"></div>

<script>
    window.onload = function(){
        var stats = initStats();//调用stat函数

        var scene = new THREE.Scene();  //定义场景

        var camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000); //定义相机

        //定义渲染器
        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xEEEEEE,1.0);
        renderer.setSize(window.innerWidth,window.innerHeight);
        //允许阴影映射：真，
        // 还需要明确定义哪些物体投射阴影，哪些物体接受阴影，
        // 以及定义哪个光源可以产生阴影
        renderer.shadowMapEnabled = true;

        //创建一个坐标轴对象并添加到场景中
        /*var axex = new THREE.AxisHelper(20);
        scene.add(axex);*/

        //创建一个平面
        var planeGeometry = new THREE.PlaneGeometry(60,40,1,1);   //宽60，高20
        var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});  //材质颜色
        var plane = new THREE.Mesh(planeGeometry,planeMaterial);   //合并在一个名叫plane的网格对象中
        plane.receiveShadow = true;//接受阴影

        //定义平面的位置
        plane.rotation.x = -0.5*Math.PI;

        plane.position.x = 0;
        plane.position.y = 0;
        plane.position.z = 0;

        scene.add(plane);

        camera.position.x = -20;
        camera.position.y = 25;
        camera.position.z = 20;
        camera.lookAt(new THREE.Vector3(5, 0, 0));  //指向场景的中心

        //创建一个聚光灯光源
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40,60,10);
        spotLight.castShadow = true;  //该光源能产生阴影
        scene.add(spotLight);
        //创建一个环境光源
       /* var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);*/

        //输出到页面
        document.getElementById('WebGL-output').appendChild(renderer.domElement);

        //自定义一个立方体
        var vertices = [
            new THREE.Vector3(1,3,1),
            new THREE.Vector3(1,3,-1),
            new THREE.Vector3(1,-1,1),
            new THREE.Vector3(1,-1,-1),
            new THREE.Vector3(-1,3,-1),
            new THREE.Vector3(-1,3,1),
            new THREE.Vector3(-1,-1,-1),
            new THREE.Vector3(-1,-1,1)
        ];

        var faces = [
            new THREE.Face3(0, 2, 1),
            new THREE.Face3(2, 3, 1),
            new THREE.Face3(4, 6, 5),
            new THREE.Face3(6, 7, 5),
            new THREE.Face3(4, 5, 1),
            new THREE.Face3(5, 0, 1),
            new THREE.Face3(7, 6, 2),
            new THREE.Face3(6, 3, 2),
            new THREE.Face3(5, 7, 0),
            new THREE.Face3(7, 2, 0),
            new THREE.Face3(1, 3, 4),
            new THREE.Face3(3, 6, 4),
        ];

        var geom = new THREE.Geometry();
        geom.vertices = vertices;
        geom.faces = faces;
        geom.computeFaceNormals();

        var materials = [
                new THREE.MeshLambertMaterial({opacity:0.6,color:0x44ff44,transparent:true}),
                new THREE.MeshBasicMaterial({color:0x000000,wireframe:true})
        ];

        var mesh = THREE.SceneUtils.createMultiMaterialObject(geom,materials);  //支持多种材质
        mesh.children.forEach(function (e) {
            e.castShadow = true      //为所有子对象添加阴影
        });

        scene.add(mesh);

        function addControl(x,y,z){
            var controls = new function(){
                this.x = x;
                this.y = y;
                this.z = z;
            };
            return controls;
        };

        var controlPoints = [];
        controlPoints.push(addControl(3,5,3));
        controlPoints.push(addControl(3,5,0));
        controlPoints.push(addControl(3,0,3));
        controlPoints.push(addControl(3, 0, 0));
        controlPoints.push(addControl(0, 5, 0));
        controlPoints.push(addControl(0, 5, 3));
        controlPoints.push(addControl(0, 0, 0));
        controlPoints.push(addControl(0, 0, 3));

        var gui = new dat.GUI();
        gui.add(new function () {
            this.clone = function () {

                var clonedGeometry = mesh.children[0].geometry.clone();
                var materials = [
                    new THREE.MeshLambertMaterial({opacity: 0.6, color: 0xff44ff, transparent: true}),
                    new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})

                ];

                var mesh2 = THREE.SceneUtils.createMultiMaterialObject(clonedGeometry, materials);
                mesh2.children.forEach(function (e) {
                    e.castShadow = true
                });

                mesh2.translateX(5);
                mesh2.translateZ(5);
                mesh2.name = "clone";
                scene.remove(scene.getChildByName("clone"));
                scene.add(mesh2);


            }
        }, 'clone');

        for (var i = 0; i < 8; i++) {

            f1 = gui.addFolder('Vertices ' + (i + 1));
            f1.add(controlPoints[i], 'x', -10, 10);
            f1.add(controlPoints[i], 'y', -10, 10);
            f1.add(controlPoints[i], 'z', -10, 10);

        }

        //在场景结束后调用一次函数来启动动画
        render();

        function render(){
            stats.update();       //实时更新

            var vertices = [];   //不要忘记加s！！！！！！
            for(var i = 0;i < 8;i++){
                vertices.push(new THREE.Vector3(controlPoints[i].x,controlPoints[i].y,controlPoints[i].z));
            }

            //对于一个顶点，无论何时修改了该顶点下拉框里的属性，这个方块都会按照修改后的位置正确的渲染出来
            mesh.children.forEach(function (e) {
                e.geometry.vertices = vertices;      //这三句代码，使用版本69的threejs能够正常使用，版本73的则不能更新！！！！！！！！！！！！！！
                e.geometry.verticesNeedUpdate = true;
                e.geometry.computeFaceNormals();

            });

            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        function initStats(){  //初始化函数，定义具体位置
            var stats = new Stats();
            stats.setMode(0);
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById('Stats-output').appendChild(stats.domElement);
            return stats;
        }

    }
</script>
</body>
</html>